<template>
  <div class="container">
    <div style="margin-bottom: 20px;">Excel</div>
    <div class="top-controls">
      <input type="file" @change="handleFileUpload" accept=".xlsx" />
      <button style="margin-left: 10px; padding: 4px 8px" @click="exportToWord">导出</button>
    </div>
    <div class="main-content">
      <div class="left-panel">
        <div>
          <el-form v-model="formObj">
            <el-form-item label="文档标题">
              <el-input v-model="formObj.label" placeholder="请输入文档标题"></el-input>
              <el-button @click="handleJump('label')">跳转</el-button>
            </el-form-item>
            <el-form-item label="文档描述">
              <el-input v-model="formObj.description" placeholder="请输入文档描述"></el-input>
            </el-form-item>
          </el-form>
        </div>
        <h3>文档目录</h3>
          <el-tree
          :data="treeData"
          :props="treeProps"
          default-expand-all
          @node-click="handleNodeClick"
          highlight-current
          :expand-on-click-node="false"
          node-key="id"
          class="doc-tree"
        >
          <template #default="{ node, data }">
            <div class="custom-tree-node">
              <span>{{ node.label }}</span>
              <div v-if="data.id >= 0 && data.level < 6">
                <el-icon @click="append(data)"><CirclePlus /></el-icon>
              </div>
            </div>
          </template>
        </el-tree>
      </div>
      <div class="right-panel">
        <button @click="handleSwitch">替换</button>
        <div id="toolbar"></div>
        <div id="editor">
        </div>
      </div>
    </div>
    <div id="editTable"></div>
  </div>
</template>

<script setup>
import { ref,onMounted, nextTick, watch, unref, reactive } from 'vue';
import { saveAs } from "file-saver";
import { ElTree, ElEmpty, 
  ElIcon, ElMessage, ElMessageBox, ElForm, ElFormItem, ElInput} from 'element-plus';
import 'element-plus/dist/index.css';
import Quill from 'quill';
// import ImageResize from 'quill-image-resize';
import QuillResizeImage from 'quill-resize-image';
import { debounce }  from 'lodash';
import {CirclePlus} from '@element-plus/icons-vue';
import "quill-mention/autoregister";
import * as XLSX from 'xlsx'

let quill;
const treeData = ref([]);
const currentNode = ref(null);
const currentContent = ref('');
const treeProps = {
  children: 'children', // 指定子节点字段名
  label: 'label',       // 指定标签字段名
  isLeaf: 'isLeaf'      // 指定是否为叶节点的字段名
};

const formObj = reactive({
  label: '安彦辉',
  description: '安达维尔',
});
const labelMap = {
  label: '文档标题',
  description: '文档描述',
}
// 生成跟变量相关的结构化模板
function generateTemplate(key, value) { 
  return `<span class="mention" 
    data-index="0" data-denotation-char="" data-id="${key}" 
    data-value="${value}"><span contenteditable="false"><span class="ql-mention-denotation-char"></span>
    <span class="ql-mention-value">${value}</span></span></span>`
}

const atValues = ref([])
watch(() => formObj, debounce((value) => {
 const keys = Object.keys(value);
 if (keys.length > 0) {
   // 把值存到atValues中
   atValues.value = keys.map(key => ({ id: key, value: value[key] }));
 }
}), {
  deep: true,
  immediate: true,
})
const handleSwitch = () => {
 let htmlContent = getQuillContentAsHtml();
 for (let i = 0; i < atValues.value.length; i++) {
   const item = atValues.value[i];
   htmlContent = replaceMentionByKey(htmlContent, item.id, item.value);
  //  console.log(htmlContent)
  quill.setContents([{ insert: '\n' }]);
  quill.clipboard.dangerouslyPasteHTML(0, htmlContent);
 }
}

// 替换函数
function replaceMentionByKey(html, key, value) {
    // 构建带参数的正则表达式，转义key中的特殊字符以确保正确匹配
    const regex = new RegExp(
        '<span class="mention"[^>]*data-id="' + 
        key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + 
        '"[^>]*>(.*?)<span class="ql-mention-value">([^<]*)</span>', 
        'gi'
    );
    
    return html.replace(regex, function(match, middleContent, currentText) {
        // 替换data-value属性（如果存在）或添加该属性
        const newDataValue = match.includes('data-value') 
            ? match.replace(/data-value="[^"]*"/, `data-value="${value}"`) 
            : match.replace('</span>', ` data-value="${value}"></span>`);
        
        // 替换ql-mention-value标签内的文本
        return newDataValue.replace(
            `<span class="ql-mention-value">${currentText}</span>`, 
            `<span class="ql-mention-value">${value}</span>`
        );
    });
}
// 跳转到制定的位置
let clickNum = 0;
let oldLabel = '';
function handleJump(label) {
  // 处理切换字段的逻辑
  if (oldLabel !== label) {
    oldLabel = label;
    clickNum = 0;
  }
  // 获取所有标题元素
  const linkNodes = Array.from(document.querySelectorAll('.mention[data-id="'+label+'"]'));
  if (linkNodes.length === 0) {
    return; 
  } else if (clickNum > linkNodes.length - 1) {
    clickNum = 0;
    return; 
  } else {
    clickNum++;
    const linkNode = linkNodes[clickNum - 1];
    // const linkBlot = Quill.find(linkNode);
    // let index = quill.getIndex(linkBlot);
    // console.log(index);
    linkNode.scrollIntoView({ behavior: 'smooth', block: 'center' });
    // linkNode.scrollTo({
    //   top: index * 13, // 减去50px的偏移量
    //   behavior:'smooth' // 平滑滚动
    // });
  }
}

onMounted(() => { 
  // 注册表格模块
  // Quill.register({
  //   'modules/table': QuillTable,
  // }, true);
  // Quill.register({
  //   'modules/table-better': QuillTableBetter
  // }, true);
  const ImageBlot = Quill.import('formats/image');
  class CustomImageBlot extends ImageBlot {
      static create(value) {
        const node = super.create(value);
        if (typeof value === 'string') {
          // 提取并应用原始样式
          const parser = new DOMParser();
          const doc = parser.parseFromString(value, 'text/html');
          const img = doc.querySelector('img');
          if (img && img.style) {
            node.setAttribute('style', img.style.cssText);
          }
        }
        return node;
      }
      
      static formats(domNode) {
        // 返回图片的样式属性，确保 Quill 不会过滤它们
        return {
          style: domNode.getAttribute('style')
        };
      }
      
      format(name, value) {
        if (name === 'style' && value) {
          this.domNode.setAttribute(name, value);
        } else {
          super.format(name, value);
        }
      }
    }
  
  // 注册自定义 Image blot
  Quill.register('formats/image', CustomImageBlot, true);
  const toolbarOptions = [
    ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
    ['blockquote', 'code-block'],
    ['link', 'image', 'video', 'formula'],

    [{ 'list': 'ordered'}, { 'list': 'bullet' }, { 'list': 'check' }],
    [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
    [{ 'indent': '-1'}, { 'indent': '+1' }],          // outdent/indent
    [{ 'direction': 'rtl' }],                         // text direction

    [{ 'header': [1, 2, 3, 4, 5, 6, false] }],

    [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
    [{ 'font': [] }],
    [{ 'align': [] }],
    ['clean'],                                        // remove formatting button
  ];
  Quill.register("modules/resize", QuillResizeImage);
  
  // 注册表格模块
  quill = new Quill('#editor', {
    theme: 'snow',
    modules:{
      table: true,
      toolbar: toolbarOptions,
      clipboard: {
        matchers: [
          // 匹配 img 标签，保留 style 属性
          ['img', (node, delta) => {
            const style = node.getAttribute('style');
            if (style) {
              delta.ops[0].attributes = delta.ops[0].attributes || {};
              delta.ops[0].attributes.style = style;
            }
            return delta;
          }]
        ]
      } ,
      resize: {
        locale: {},
      },
      mention: {
        allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
        mentionDenotationChars: ["@"], 
        allowInlineMentionChar: true,
        showDenotationChar: false, // 是否显示@符号
        source: function(searchTerm, renderList, mentionChar) {
          var values;
          if (mentionChar === "@") {
            values = atValues.value; 
          }
          if (searchTerm.length === 0) {
            renderList(values, searchTerm); 
          }
          else {
            var matches = [];
            for (var i = 0; i < values.length; i++) {
              if (~values[i].toLowerCase().indexOf(searchTerm.toLowerCase())) {
                matches.push(values[i]);
              }
            } 
            renderList(matches, searchTerm);
          }
        },
        renderItem: function(item) {
          // 这里显示 ID，但实际选择后会插入 value
          return `${labelMap[item.id]} - ${item.value}`;
        },
        insertTrigger: true, // 插入触发后的内容
        onSelect: function(item, insertItem) {
          // 可在此处处理选中事件
          insertItem(item);
        }
      },
    },
  });
  // 监听内容变化并触发保存
  // quill.on('text-change', (delta, oldDelta, source) => {
  //   if (source === 'user') {  // 只处理用户操作
  //     // 获取编辑器里的内容
  //     let htmlContent = getQuillContentAsHtml();
  //     // 进行目录结构的更新
  //     if (currentNode.value && currentNode.value.label !== '全文') {
  //       // 更新当前节点的HTML内容
  //       // todo: 解析htmlContent，更新当前节点的content属性和children属性，同时更新treeData
  //       currentNode.value.content = htmlContent;
  //     } else {
  //       const debouncedFetch = debounce(convertToElTree, 300);
  //       debouncedFetch(htmlContent)
  //     }
  //     // currentNode.value.content = htmlContent;
  //     // 从treeData中查找到当前节点
  //     // const node = findNodeInTreeData(currentNode.value, treeData.value);
  //   }
  // });
    
});
let workbook = ''
const handleFileUpload = async (e) => {
  quill.setContents([{ insert: '\n' }]);
  treeData.value = [];
  const file = e.target.files[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onload = async (event) => {
    try {
      const data = new Uint8Array(event.target.result);
      workbook = XLSX.read(data, { 
        type: 'array',
        cellDates: true,    // 解析日期格式
        cellFormula: true,  // 保留公式
        cellStyles: true    // 保留样式信息 
      });
      console.log(workbook)
      // 获取所有表名
      const sheetNames = workbook.SheetNames;
      
      // 循环读取每个表
      let resultContent = [];
      for (let i = 0; i < sheetNames.length; i++) {
        const sheetName = sheetNames[i];
        const sheet = workbook.Sheets[sheetName];
         // 检查特定单元格（如A1）
        if (!sheet['A1']) continue;
        // 检查合并单元格
        if (sheet['!merges'] && sheet['!merges'].length > 0) {
          console.log('合并单元格数量:', sheet['!merges'].length);
        }
        const html = excelSheetToTable(sheet);

        const node ={
          id: sheetName,
          label: sheetName,
          level: 1,
          content: html,
          isLeaf: true,
          children: []
        }
        resultContent.push(node)
      }
    console.log('resultContent:', resultContent);
      
      // // 去掉resultContent中<style></style>标签
      // resultContent = resultContent.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '');
      
      // quill.clipboard.dangerouslyPasteHTML(0, resultContent);
      convertToElTree(resultContent)
    } catch (error) {
      console.error('转换失败:', error);
      console.error('错误堆栈:', error.stack);
    }
  };
  reader.readAsArrayBuffer(file);
};
// 将Excel工作表转换为HTML表格，处理合并单元格和日期格式
function excelSheetToTable(sheet) {
  const range = XLSX.utils.decode_range(sheet['!ref'] || 'A1');
  const merges = sheet['!merges'] || [];
  const merged = new Set(); // 标记已处理的合并单元格（地址：如"A1"）

  // 预处理：标记所有合并区域的单元格
  merges.forEach(merge => {
    for (let r = merge.s.r; r <= merge.e.r; r++) {
      for (let c = merge.s.c; c <= merge.e.c; c++) {
        merged.add(XLSX.utils.encode_cell({ r, c }));
      }
    }
  });

  // 检查单元格是否为日期类型
  function isDateCell(cell, styles) {
    if (!cell || !cell.t) return false;
    // 数字类型且有样式信息
    if (cell.t === 'd' && cell.z) {
      // Excel日期格式通常包含y/m/d等字符
      const format = cell.z.toLowerCase();
      return format.includes('y') || format.includes('m') || format.includes('d');
    }
    // // 检查样式表中的日期格式
    // if (cell.s !== undefined && styles && styles.Stylesheet && styles.Stylesheet.numFmts) {
    //   const style = styles.Stylesheet.cellXfs.xf[cell.s];
    //   if (style && style.numFmtId !== undefined) {
    //     const numFmtId = style.numFmtId;
    //     const numFmt = styles.Stylesheet.numFmts.numFmt.find(fmt => fmt.numFmtId === numFmtId);
    //     if (numFmt) {
    //       const format = numFmt.formatCode.toLowerCase();
    //       return format.includes('y') || format.includes('m') || format.includes('d');
    //     }
    //   }
    // }
    return false;
  }

  // 将Excel日期数字转换为YYYY-MM-DD格式
  function formatExcelDate(excelDate) {
    
    if (typeof excelDate !== 'number') {
      excelDate = new Date(excelDate).getTime()
    }
    // Excel日期是从1900年1月1日开始的天数（有一些闰年的小问题）
    const date = new Date((excelDate - 25569));
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}.${month}.${day}`;
  }

  let tableHtml = '<table class="border-collapse w-full">';

  for (let r = range.s.r; r <= range.e.r; r++) {
    tableHtml += '<tr>';
    for (let c = range.s.c; c <= range.e.c; c++) {
      const cellAddr = XLSX.utils.encode_cell({ r, c });
      const isMerged = merged.has(cellAddr);
      const cell = sheet[cellAddr] || {};
      
      // 仅处理合并区域的【左上角单元格】或普通单元格
      if (isMerged) {
        const merge = merges.find(m => 
          r >= m.s.r && r <= m.e.r && c >= m.s.c && c <= m.e.c
        );
        if (!merge) continue;

        // 仅左上角单元格渲染
        if (merge.s.r !== r || merge.s.c !== c) continue;

        const rowspan = merge.e.r - merge.s.r + 1;
        const colspan = merge.e.c - merge.s.c + 1;
        let value = cell.w !== undefined ? cell.w : (cell.v || '');
        
        // 日期格式处理
        if (isDateCell(cell, sheet['!styles'])) {
          value = formatExcelDate(cell.v);
          console.log(value)
        }
        
        const style = getCellStyle(cell, sheet['!styles'], sheet['!cf']);
        
        tableHtml += `
          <td 
            rowspan="${rowspan}" 
            colspan="${colspan}" 
            class="p-2 text-sm ${style.classes}"
            style="${style.inline}"
          >${value}</td>
        `;
      } else {
        let value = cell.w !== undefined ? cell.w : (cell.v || '');
        
        // 日期格式处理
        if (isDateCell(cell, sheet['!styles'])) {
          value = formatExcelDate(cell.v).toString();
        }
        
        const style = getCellStyle(cell, sheet['!styles'], sheet['!cf']);
        
        tableHtml += `
          <td 
            class="p-2 text-sm ${style.classes}"
            style="${style.inline}"
          >${value}</td>
        `;
      }
    }
    tableHtml += '</tr>';
  }

  tableHtml += '</table>';
  return tableHtml;
}

// 辅助函数：从单元格获取样式并转换为HTML可用格式
function getCellStyle(cell, styles, conditionalFormats) {
  if (!cell || !styles) return { inline: '', classes: '' };
  
  // 基础样式
  let inlineStyles = [];
  let classes = [];
  
  // 应用条件格式样式（如果有）
  const cfStyle = getConditionalFormatStyle(cell, styles, conditionalFormats);
  if (cfStyle) {
    inlineStyles.push(cfStyle.inline);
    classes.push(cfStyle.classes);
  }
  
  // 获取单元格的样式索引
  const styleId = cell.s;
  if (styleId === undefined) return { inline: inlineStyles.join(' '), classes: classes.join(' ') };
  
  // 获取样式信息
  const cellXf = styles['xf'][styleId];
  if (!cellXf) return { inline: inlineStyles.join(' '), classes: classes.join(' ') };
  
  const numFmtId = cellXf.numFmtId || 0;
  const fontId = cellXf.fontId || 0;
  const fillId = cellXf.fillId || 0;
  const alignment = cellXf.alignment || {};
  const borderId = cellXf.borderId || 0;
  
  // 处理对齐方式
  if (alignment.horizontal) {
    inlineStyles.push(`text-align: ${alignment.horizontal};`);
    classes.push(`text-${alignment.horizontal}`);
  }
  if (alignment.vertical) {
    inlineStyles.push(`vertical-align: ${alignment.vertical};`);
  }
  if (alignment.wrapText) {
    inlineStyles.push(`white-space: normal; word-wrap: break-word;`);
  }
  
  // 处理字体
  const font = styles['fonts'][fontId] || {};
  if (font.name) {
    inlineStyles.push(`font-family: "${font.name}", sans-serif;`);
  }
  if (font.sz) {
    inlineStyles.push(`font-size: ${font.sz}pt;`);
  }
  if (font.b) {
    inlineStyles.push(`font-weight: bold;`);
    classes.push('font-bold');
  }
  if (font.i) {
    inlineStyles.push(`font-style: italic;`);
    classes.push('italic');
  }
  if (font.u) {
    inlineStyles.push(`text-decoration: underline;`);
    classes.push('underline');
  }
  if (font.strike) {
    inlineStyles.push(`text-decoration: line-through;`);
    classes.push('line-through');
  }
  if (font.color && font.color.rgb) {
    inlineStyles.push(`color: #${font.color.rgb};`);
  }
  
  // 处理背景
  const fill = styles['fills'][fillId] || {};
  const patternFill = fill.patternFill || {};
  if (patternFill.fgColor && patternFill.fgColor.rgb) {
    inlineStyles.push(`background-color: #${patternFill.fgColor.rgb};`);
    classes.push(`bg-[#${patternFill.fgColor.rgb}]`);
  }
  
  // 处理边框
  const border = styles['borders'][borderId] || {};
  const borderStyles = getBorderStyles(border);
  inlineStyles.push(borderStyles.inline);
  classes.push(borderStyles.classes);
  
  return {
    inline: inlineStyles.join(' '),
    classes: classes.join(' ')
  };
}

// 处理条件格式样式
function getConditionalFormatStyle(cell, styles, conditionalFormats) {
  if (!conditionalFormats || !Array.isArray(conditionalFormats)) return null;
  
  const cellAddr = XLSX.utils.encode_cell({ r: cell.r, c: cell.c });
  
  // 检查是否有适用于此单元格的条件格式
  for (const cf of conditionalFormats) {
    if (cf.ranges.some(range => isCellInRange(cellAddr, range))) {
      // 找到匹配的条件格式
      for (const rule of cf.rules) {
        if (rule.dxfId !== undefined) {
          // 应用差异样式
          const dxf = styles['dxf'][rule.dxfId] || {};
          return formatDxfStyle(dxf);
        }
      }
    }
  }
  
  return null;
}

// 检查单元格是否在范围内
function isCellInRange(cellAddr, range) {
  const parsedRange = XLSX.utils.decode_range(range);
  const cellRef = XLSX.utils.decode_cell(cellAddr);
  
  return (
    cellRef.r >= parsedRange.s.r &&
    cellRef.r <= parsedRange.e.r &&
    cellRef.c >= parsedRange.s.c &&
    cellRef.c <= parsedRange.e.c
  );
}

// 格式化差异样式
function formatDxfStyle(dxf) {
  const inline = [];
  const classes = [];
  
  // 处理字体样式
  if (dxf.font) {
    const font = dxf.font;
    if (font.color && font.color.rgb) {
      inline.push(`color: #${font.color.rgb};`);
    }
    if (font.b) {
      inline.push(`font-weight: bold;`);
      classes.push('font-bold');
    }
    if (font.i) {
      inline.push(`font-style: italic;`);
      classes.push('italic');
    }
    if (font.u) {
      inline.push(`text-decoration: underline;`);
      classes.push('underline');
    }
    if (font.strike) {
      inline.push(`text-decoration: line-through;`);
      classes.push('line-through');
    }
  }
  
  // 处理填充样式
  if (dxf.fill) {
    const fill = dxf.fill;
    const patternFill = fill.patternFill || {};
    if (patternFill.fgColor && patternFill.fgColor.rgb) {
      inline.push(`background-color: #${patternFill.fgColor.rgb};`);
      classes.push(`bg-[#${patternFill.fgColor.rgb}]`);
    }
  }
  
  return { inline: inline.join(' '), classes: classes.join(' ') };
}

// 处理边框样式
function getBorderStyles(border) {
  const inline = [];
  const classes = [];
  
  // 边框样式映射
  const styleMap = {
    'thin': '1px solid',
    'medium': '2px solid',
    'thick': '3px solid',
    'dashed': '1px dashed',
    'dotted': '1px dotted',
    'double': '3px double'
  };
  
  // 处理各边边框
  ['left', 'right', 'top', 'bottom', 'diagonal'].forEach(side => {
    if (border[side]) {
      const sideBorder = border[side];
      const style = sideBorder.style || 'thin';
      const color = sideBorder.color && sideBorder.color.rgb ? `#${sideBorder.color.rgb}` : '#000000';
      
      if (styleMap[style]) {
        if (side === 'diagonal') {
          // 对角线边框在HTML中难以直接表示，这里忽略
        } else {
          inline.push(`${side}-border: ${styleMap[style]} ${color};`);
          classes.push(`border-${side}`);
        }
      }
    }
  });
  
  return { inline: inline.join(' '), classes: classes.join(' ') };
}

// 生成目录结构
const convertToElTree = (resultContent) => {
  if (!resultContent) {
    console.error('未找到标题结构');
    return;
  }
  treeData.value = resultContent;
};

const append = (data) => {
   ElMessageBox.prompt('请输入标题内容', 'Tip', {
    confirmButtonText: 'OK',
    cancelButtonText: 'Cancel',
  })
    .then(({ value }) => {
      if (data.level >=  6) {
        ElMessage({
          type: 'info',
          message: '标题层级不能超过6级',
        })
      } else {
        let currentLevel = data.level + 1;
        let currentContent = `<h${currentLevel}>${value}</h${currentLevel}>`;
        const newChild = { id: data.id++, level: currentLevel, label: value, children: [] ,content: currentContent}
        if (!data.children) {
          data.children = []
        }
        data.children.push(newChild)
        treeData.value = [...treeData.value]
      }
    })
    .catch(() => {
      ElMessage({
        type: 'info',
        message: 'Input canceled',
      })
    })
};



// 节点点击处理函数
const handleNodeClick = (node) => {
  console.log('点击了节点：', node);
  // 更新当前选中节点
  currentNode.value = node;
  const isFullText = node.label == '全文' && node.children && node.children.length > 0;
  
  // 构建包含当前节点及其所有子节点内容的HTML
  // const combinedContent = buildCombinedContent(node, isFullText);
  
  // 更新内容区域
  // currentContent.value = combinedContent;
  quill.root.innerHTML = '';
  // quill.clipboard.dangerouslyPasteHTML(0, currentContent.value);
  quill.root.innerHTML = node.content.toString();
};
// HTML 转 Delta 函数
function htmlToQuillDelta(html) {
  const parser = new DOMParser();
  const doc = parser.parseFromString(html, 'text/html');
  const table = doc.querySelector('table');
  
  if (!table) return { ops: [] };
  
  const delta = { ops: [{ insert: { table: [] } }] };
  const rowData = [];
  
  Array.from(table.rows).forEach((row, rowIndex) => {
    const cells = [];
    Array.from(row.cells).forEach(cell => {
      cells.push({
        value: cell.textContent,
        attributes: {
          rowspan: cell.getAttribute('rowspan') || 1,
          colspan: cell.getAttribute('colspan') || 1
        }
      });
    });
    delta.ops[0].insert.table.push(cells);
  });
  
  return delta;
}
/**
 * 构建包含当前节点及其所有子节点内容的HTML（修复版）
 * @param {Object} node - 当前节点
 * @returns {string} - 组合后的HTML内容
 */
 function buildCombinedContent(node, isFullText,includeSelf = true) {
  const container = document.createElement('div');
  
  // 添加当前节点的内容（如果需要）
  if (includeSelf && node.content) {
    container.innerHTML = node.content;
  }
  
  // // 递归添加所有子节点的内容
  if (isFullText) {
    const childrenContainer = document.createElement('div');
    childrenContainer.className = 'node-children-content';
    
    node?.children?.forEach(child => {
      // 直接使用子节点的完整内容（已包含标题和内容）
      const childContent = buildCombinedContent(child, isFullText, true);
      childrenContainer.innerHTML += childContent;
    });
    
    if (childrenContainer.innerHTML) {
      container.appendChild(childrenContainer);
    }
  }
  
  return container.innerHTML;
}

  const exportToWord =  () => {
    const parser = new DOMParser();
    const doc = parser.parseFromString(quill.root.innerHTML, 'text/html');
    exportTableWithStylesToExcel(doc, 'styled_table.xlsx', { sheetName: 'Sheet1' });
  }
function exportTableWithStylesToExcel(table, fileName = 'styled_table.xlsx', options = {}) {
  const tableElement = typeof table === 'string' 
    ? document.getElementById(table) 
    : table;
  let tableHtml = tableElement.querySelector('table');
  if (!tableHtml || tableHtml.tagName !== 'TABLE') {
    throw new Error('未找到表格元素或参数不是有效的表格');
  }
  
  // 创建基本工作表
  const ws = XLSX.utils.table_to_sheet(tableHtml);
  
  // 映射HTML样式到Excel样式
  mapHtmlStylesToSheet(tableHtml, ws);
  
  // 创建工作簿并添加工作表
  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, options.sheetName || 'Sheet1');
  
  // 导出为Excel文件
  XLSX.writeFile(wb, fileName);
}

/**
 * 将HTML表格样式映射到工作表
 * @param {HTMLElement} tableElement - 表格元素
 * @param {Object} ws - SheetJS工作表对象
 */
function mapHtmlStylesToSheet(tableElement, ws) {
  // 获取所有单元格
  const rows = tableElement.querySelectorAll('tr');
  
  rows.forEach((row, rowIndex) => {
    const cells = row.querySelectorAll('td, th');
    
    cells.forEach((cell, colIndex) => {
      const cellAddress = XLSX.utils.encode_cell({ r: rowIndex, c: colIndex });
      const cellObj = ws[cellAddress];
      
      if (!cellObj) return;
      
      // 获取单元格样式
      const style = window.getComputedStyle(cell);
      const cellStyle = {};
      
      // 映射文本样式
      if (style.fontWeight === 'bold' || style.fontWeight >= 700) {
        cellStyle.bold = true;
      }
      if (style.fontStyle === 'italic') {
        cellStyle.italic = true;
      }
      if (style.textDecoration.includes('underline')) {
        cellStyle.underline = true;
      }
      
      // 映射颜色
      if (style.color !== 'rgb(0, 0, 0)') {
        cellStyle.color = { rgb: hexColor(style.color) };
      }
      
      // 映射背景色
      if (style.backgroundColor !== 'rgba(0, 0, 0, 0)' && style.backgroundColor !== 'transparent') {
        cellStyle.fill = {
          patternType: 'solid',
          fgColor: { rgb: hexColor(style.backgroundColor) }
        };
      }
      
      // 应用样式到单元格
      if (Object.keys(cellStyle).length > 0) {
        cellObj.s = cellStyle;
      }
    });
  });
}

/**
 * 将RGB颜色转换为十六进制
 * @param {string} rgb - RGB颜色值 (例如: "rgb(255, 0, 0)")
 * @returns {string} - 十六进制颜色值 (例如: "FF0000")
 */
function hexColor(rgb) {
  if (rgb.startsWith('#')) return rgb.substring(1);
  
  const rgbArray = rgb.match(/\d+/g);
  if (!rgbArray || rgbArray.length < 3) return '000000';
  
  return rgbArray.slice(0, 3).map(n => {
    const hex = parseInt(n, 10).toString(16);
    return hex.length === 1 ? '0' + hex : hex;
  }).join('').toUpperCase();
}

</script>

<style scoped>
.top-controls {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 20px;
}

.export-btn {
  padding: 8px 16px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.export-btn:hover {
  background: #0056b3;
  text-decoration: none;
}

.container {
  padding: 20px;
}

.main-content {
  display: flex;
  margin-top: 20px;
  gap: 20px;
}

.left-panel {
  flex: 1;
  max-width: 300px;
  border-right: 1px solid #ccc;
  padding-right: 20px;
}

.right-panel {
  flex: 3;
}

button {
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  color: #007bff;
  margin: 5px 0;
}

button:hover {
  text-decoration: underline;
}

ul {
  list-style-type: none;
  padding-left: 20px;
}

.toolbar {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  margin-bottom: 10px;
}

.editor {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  height: 500px;
  overflow: auto;
  padding: 15px;
}
</style>

<style>
#editor {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  height: 500px;
  overflow: auto;
  padding: 15px;
}
#A{
  display: none;
}
/* 全局样式确保v-html中的表格正确显示 */
.right-panel table {
  border-collapse: collapse;
  width: 100%;
  margin: 10px 0;
}
.right-panel td, .right-panel th {
  border: 1px solid #ddd;
  padding: 8px;
}
/*
.right-panel tr:nth-child(even) {
  background-color: #f2f2f2;
}*/
  .right-panel p {
    margin: 10px 0;
    line-height: 1.6;
    font-size: 16px;
  }
  .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
  }
  .ql-mention-value {
    color: blue;
  }
  .ql-editor table {
  border-collapse: collapse !important;
  width: 100%;
  margin-bottom: 1em;
}

.ql-editor td {
  border: 1px solid #ccc !important;
  padding: 6px 12px !important;
  vertical-align: top !important;
}
/* 可选：高亮显示合并单元格
.ql-editor td[rowspan],
.ql-editor td[colspan] {
  background-color: #f9f9f9; 
}*/
</style>